PROYECTO DE CLASE - ANÁLISIS DE SERIES DE TIEMPO

SERIE: ANÁLISIS DE COTIZACIONES EN BOLSA - ACCIONES DE ARGOS

Integrantes:

  • Cesar Prieto
  • Gabriel Peña
  • Sebastian Gil

INTRODUCCION

La base de datos fue tomada de la pagina https://es.investing.com/equities/grupoargos-historical-data la cual proporciona estos datos de manera gratuita al publico, la inspiracion para desarrollar este trabajo con esta base es conocer como se comportan los metodos aprendidos en clase en un enfoque econocimo y sobre todo en el area de las acciones, con lo cual decidimos tomar los datos de un grupo empresarial Colombiano y realizar el analisis correspondiente para desarrollar el proyecto para la clase de series de tiempo.

Descripcion de la base:

  • Acciones DIARIAS del Grupo ARGOS
  • 3401 Datos tomado (Desde el 7/11/20114 Hasta 28/02/2024)
  • Variables: Fecha, Último, Apertura, Máximo, Mínimo, Vol, %Var.
In [1]:
# Color2  <span style="color: #03396c;"></span>

DESARROLLO

IMPORTACION Y LIMPIEZA DE DATOS

Paquetes necesarios para el desarrollo del problema

In [5]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
import plotly.express as px
from sklearn import __version__ as sklearn_version
from sklearn import *
In [6]:
# Ruta del archivo CSV
archivo_csv = r'C:\Users\HP\OneDrive\Documentos\DOCUMENTOS PERSONAJES\CESAR\Series\Pro_Series\Series-de-Tiempo\Datos\G_ARGOS.csv'

# Cargar el archivo CSV en un DataFrame de pandas
ARGOS = pd.read_csv(archivo_csv, sep=';')
In [7]:
ARGOS.info()
print(ARGOS)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3401 entries, 0 to 3400
Data columns (total 7 columns):
 #   Column    Non-Null Count  Dtype 
---  ------    --------------  ----- 
 0   Fecha     3401 non-null   object
 1   Último    3401 non-null   object
 2   Apertura  3401 non-null   object
 3   Máximo    3401 non-null   object
 4   Mínimo    3401 non-null   object
 5   Vol.      3401 non-null   object
 6   % var.    3401 non-null   object
dtypes: object(7)
memory usage: 186.1+ KB
           Fecha     Último   Apertura     Máximo     Mínimo     Vol.  % var.
0     28/02/2024  13.840,00  13.360,00  13.840,00  13.360,00  173,30K   2,37%
1     27/02/2024  13.520,00  13.600,00  13.600,00  13.480,00   85,25K   0,00%
2     26/02/2024  13.520,00  13.280,00  13.560,00  13.280,00   53,98K  -0,44%
3     25/02/2024  13.580,00  13.020,00  13.600,00  13.000,00  397,70K   2,41%
4     24/02/2024  13.260,00  13.000,00  13.260,00  13.000,00   51,67K   2,31%
...          ...        ...        ...        ...        ...      ...     ...
3396  11/11/2014  18.800,00  19.000,00  19.000,00  18.640,00  449,45K  -0,95%
3397  10/11/2014  18.980,00  19.500,00  19.500,00  18.980,00  704,07K  -3,16%
3398  09/11/2014  19.600,00  19.800,00  19.800,00  19.600,00  901,59K  -1,90%
3399  08/11/2014  19.980,00  19.960,00  20.000,00  19.880,00  124,71K   0,00%
3400  07/11/2014  19.980,00  19.900,00  19.980,00  19.880,00   59,52K   0,00%

[3401 rows x 7 columns]
In [8]:
# Convertir la columna de fecha al formato de fecha
ARGOS['Fecha'] = pd.to_datetime(ARGOS['Fecha'], format='%d/%m/%Y')

# Convertir las comas en los puntos en las columnas numéricas
columnas_numericas = ['Último', 'Apertura', 'Máximo', 'Mínimo']
# Eliminar los puntos de los números antes de convertirlos a float
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].replace('\,', '.', regex=True)
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].replace('\.', '', regex=True)

# Convertir las columnas numéricas al tipo float
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].astype(float)

# Dividir entre 1000 para eliminar los ceros adicionales
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].div(100000)

# Reordenar el DataFrame por fecha de la más antigua a la más reciente
ARGOS = ARGOS.sort_values(by='Fecha')

# Reiniciar el índice
ARGOS = ARGOS.reset_index(drop=True)
In [9]:
ARGOS.info()
print(ARGOS)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3401 entries, 0 to 3400
Data columns (total 7 columns):
 #   Column    Non-Null Count  Dtype         
---  ------    --------------  -----         
 0   Fecha     3401 non-null   datetime64[ns]
 1   Último    3401 non-null   float64       
 2   Apertura  3401 non-null   float64       
 3   Máximo    3401 non-null   float64       
 4   Mínimo    3401 non-null   float64       
 5   Vol.      3401 non-null   object        
 6   % var.    3401 non-null   object        
dtypes: datetime64[ns](1), float64(4), object(2)
memory usage: 186.1+ KB
          Fecha  Último  Apertura  Máximo  Mínimo     Vol.  % var.
0    2014-11-07   19.98     19.90   19.98   19.88   59,52K   0,00%
1    2014-11-08   19.98     19.96   20.00   19.88  124,71K   0,00%
2    2014-11-09   19.60     19.80   19.80   19.60  901,59K  -1,90%
3    2014-11-10   18.98     19.50   19.50   18.98  704,07K  -3,16%
4    2014-11-11   18.80     19.00   19.00   18.64  449,45K  -0,95%
...         ...     ...       ...     ...     ...      ...     ...
3396 2024-02-24   13.26     13.00   13.26   13.00   51,67K   2,31%
3397 2024-02-25   13.58     13.02   13.60   13.00  397,70K   2,41%
3398 2024-02-26   13.52     13.28   13.56   13.28   53,98K  -0,44%
3399 2024-02-27   13.52     13.60   13.60   13.48   85,25K   0,00%
3400 2024-02-28   13.84     13.36   13.84   13.36  173,30K   2,37%

[3401 rows x 7 columns]

Hasta este punto solo hemos preparado nuestros datos, asegurandonos que las variables tuvieran el tipo correcto de dato, y para una exploracion más sencilla la conversion o el reescalado de las variables numericas que respresentan un valor de la accion, las cuales son: Último, Apertura, Máximo y Mínimo, este reescalado mencionado consiste en eliminar los miles "000", es decir 3 ceros, de los valores obtenidos.

A continuacion nos disponemos a revisar como se verian las series de estas variables.

In [10]:
import plotly.graph_objects as go

# Crear una figura de plotly
fig = go.Figure()

# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Apertura'], mode='lines', name='Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Último'], mode='lines', name='Último'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Máximo'], mode='lines', name='Máximo'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Mínimo'], mode='lines', name='Mínimo'))

# Actualizar el diseño del botón
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(label="Apertura",
                     method="update",
                     args=[{"visible": [True, False, False, False]},
                           {"title": "Serie de tiempo variable Apertura"}]),
                dict(label="Último",
                     method="update",
                     args=[{"visible": [False, True, False, False]},
                           {"title": "Serie de tiempo variable Último"}]),
                dict(label="Máximo",
                     method="update",
                     args=[{"visible": [False, False, True, False]},
                           {"title": "Serie de tiempo variable Máximo"}]),
                dict(label="Mínimo",
                     method="update",
                     args=[{"visible": [False, False, False, True]},
                           {"title": "Serie de tiempo variable Mínimo"}])
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.05,
            xanchor="left",
            y=1.15,
            yanchor="top"
        ),
    ]
)

# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)

# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')

# Actualizar el título del gráfico
fig.update_layout(title='Series de tiempo de variables ARGOS')

# Mostrar el gráfico
fig.show()

Del gafico anterio podemos conlcuir que todas las variables se comportan de manera similar en el tiempo explorado, por lo cual la eleccion de la variable en la que nos centraremos no tendra una influencia positiva o negativa en nuestro estudio, sin embargo podemos notar que entre el 2021 y 2022 hubo una caida muy brusca del precio de las acciones del grupo ARGOS lo cual si podra afectar de manera directa los resultados que obtengamos.

Recomendacion: Tratar de realizar la exploracion de la serie antes de la caida y comparar resultados

ELECCION DE LA VARIABLE Y DESARROLLO DE METODOLOGIAS

En la parte anterior del codigo pudimos ver como todas las variables poseen un comportamiento bastante parecido, lo cual tiene sentido en el ambito en el cual nos encontramos, dado que estamos hablando del precio de las acciones de una compañia y este suele comportarce de forma muy similar hablando en terminos de las variables del precio de la apertura, el precio maximo y minimo o el cierre.

Por esto hemos decidido que la variable elegida para desarrollar el proyecto sera la Apertura o mejor dicho el precio de la apertura diaria del valor de la accion en la bolsa para el Grupo Argos, en miles de pesos Colombianos. Teniendo esto en cuenta, tambien podríamos aplicar el siguiente desarrollo a las otras variables pero eso no sera tema principal en este documento.

In [11]:
# Seleccionar las columnas 'Fecha' y 'Apertura' del DataFrame ARGOS
Serie = ARGOS[['Fecha', 'Apertura']]

# Visualizar las primeras filas de la serie
print(Serie.head())

# Resumen estadístico de la serie
print(Serie.describe())
       Fecha  Apertura
0 2014-11-07     19.90
1 2014-11-08     19.96
2 2014-11-09     19.80
3 2014-11-10     19.50
4 2014-11-11     19.00
                               Fecha     Apertura
count                           3401  3401.000000
mean   2019-07-03 23:59:59.999999744    16.919274
min              2014-11-07 00:00:00     7.100000
25%              2017-03-06 00:00:00    13.930000
50%              2019-07-04 00:00:00    17.980000
75%              2021-10-31 00:00:00    19.720000
max              2024-02-28 00:00:00    24.400000
std                              NaN     3.987770
In [12]:
# Crear una serie de tiempo con Pandas Time Series (ts)
Apertura = pd.Series(Serie['Apertura'].values, index=Serie['Fecha'])

import plotly.graph_objects as go
import pandas as pd

# Crear una serie de tiempo con Pandas Time Series (ts)
Apertura = pd.Series(Serie['Apertura'].values, index=Serie['Fecha'])

# Crear la figura de Plotly
fig = go.Figure()

# Agregar la serie de tiempo al gráfico
fig.add_trace(go.Scatter(x=Apertura.index, y=Apertura.values, mode='lines'))

# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)

# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor de Apertura')

# Actualizar el título del gráfico
fig.update_layout(title='Serie de tiempo OPEN')

# Mostrar el gráfico
fig.show()

TRANSFORMACION DE BOX-COX PARA REDUCCION DE LA VARIANZA

In [15]:
import numpy as np
from scipy import stats
from scipy.stats import boxcox
import matplotlib.pyplot as plt

# Calcular el lambda óptimo para la transformación de Box-Cox
fitted_data, fitted_lambda = stats.boxcox(ARGOS['Apertura'])
print("Lambda óptimo para Box-Cox:", fitted_lambda)

# Aplicar la transformación de Box-Cox a la serie de tiempo de Apertura
serie_boxcox = boxcox(Apertura, lmbda=fitted_lambda)
print(serie_boxcox)
Lambda óptimo para Box-Cox: 2.1723466235235915
[304.77160462 306.77434326 301.44940865 ... 126.3184058  133.04859268
 127.9833468 ]
In [16]:
# Crear una figura de plotly
fig = go.Figure()

# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Apertura'], mode='lines', name='Serie de tiempo Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=serie_boxcox, mode='lines', name='Serie de tiempo Apertura-BoxCox', visible=False))

# Actualizar el diseño del botón
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(label="Serie de tiempo Apertura",
                     method="update",
                     args=[{"visible": [True, False]},
                           {"title": "Serie de tiempo Apertura"}]),
                dict(label="Serie de tiempo Apertura-BoxCox",
                     method="update",
                     args=[{"visible": [False, True]},
                           {"title": "Serie de tiempo Apertura-BoxCox"}])
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.05,
            xanchor="left",
            y=1.15,
            yanchor="top"
        ),
    ]
)

# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)

# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')

# Actualizar el título del gráfico
fig.update_layout(title='Comparación de series de tiempo de Apertura')

# Mostrar el gráfico
fig.show()

TRANSFORMACION LOGARITMICA

In [17]:
# Calcular el lambda óptimo para la transformación logarítmica
optimal_lambda_log = np.argmax(np.abs(np.diff(np.log(Apertura))))
print("Lambda óptimo para transformación logarítmica:", optimal_lambda_log)

# Aplicar la transformación logarítmica a la serie de tiempo de Apertura
serie_log_apertura = np.log(Apertura)
Lambda óptimo para transformación logarítmica: 2477
In [18]:
# Crear una figura de plotly
fig = go.Figure()

# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=serie_log_apertura, mode='lines', name='Serie de tiempo Log-Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=Apertura, mode='lines', name='Serie de tiempo Apertura', visible=False))

# Actualizar el diseño del botón
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(label="Serie de tiempo Log-Apertura",
                     method="update",
                     args=[{"visible": [True, False]},
                           {"title": "Serie de tiempo Log-Apertura"}]),
                dict(label="Serie de tiempo Apertura",
                     method="update",
                     args=[{"visible": [False, True]},
                           {"title": "Serie de tiempo Apertura"}])
            ]),
            direction="down",
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.05,
            xanchor="left",
            y=1.15,
            yanchor="top"
        ),
    ]
)

# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)

# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')

# Actualizar el título del gráfico
fig.update_layout(title='Comparación de series de tiempo de Log-Apertura')

# Mostrar el gráfico
fig.show()

A partir de este punto intentaremos mostrar los resultados para ambas series teniendo en cuenta los datos en su escala original y los datos en escala log, esto con la intencion de tener una comparacion más directa sobre lo que puede causar la tranformacion de los datos en los resultados de nuestro ejercicio.

ESTIMACION Y ELIMINACION DE LA TENDENCIA

In [19]:
import statsmodels.api as sm

# Estimación de la tendencia utilizando lm (regresión lineal) para datos originales
X_original = sm.add_constant(np.arange(len(ARGOS["Apertura"])))  # Añadir una columna de unos para intercepto
fit_Apertura_original = sm.OLS(ARGOS["Apertura"], X_original).fit()

# Imprimir resumen del modelo para datos originales
print(fit_Apertura_original.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:               Apertura   R-squared:                       0.537
Model:                            OLS   Adj. R-squared:                  0.537
Method:                 Least Squares   F-statistic:                     3938.
Date:                Sun, 07 Apr 2024   Prob (F-statistic):               0.00
Time:                        19:19:31   Log-Likelihood:                -8221.3
No. Observations:                3401   AIC:                         1.645e+04
Df Residuals:                    3399   BIC:                         1.646e+04
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const         21.9772      0.093    236.116      0.000      21.795      22.160
x1            -0.0030   4.74e-05    -62.752      0.000      -0.003      -0.003
==============================================================================
Omnibus:                     2345.746   Durbin-Watson:                   0.014
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              196.750
Skew:                           0.026   Prob(JB):                     1.89e-43
Kurtosis:                       1.823   Cond. No.                     3.93e+03
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 3.93e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
In [20]:
# Modelo en escala log para los datos en escala logarítmica
log_original_data = np.log(ARGOS["Apertura"])
X_log = sm.add_constant(np.arange(len(log_original_data)))  # Añadir una columna de unos para intercepto
fit_logApertura_log = sm.OLS(log_original_data, X_log).fit()

# Imprimir resumen del modelo en escala log para los datos en escala logarítmica
print(fit_logApertura_log.summary())
                            OLS Regression Results                            
==============================================================================
Dep. Variable:               Apertura   R-squared:                       0.540
Model:                            OLS   Adj. R-squared:                  0.540
Method:                 Least Squares   F-statistic:                     3995.
Date:                Sun, 07 Apr 2024   Prob (F-statistic):               0.00
Time:                        19:19:34   Log-Likelihood:                 952.38
No. Observations:                3401   AIC:                            -1901.
Df Residuals:                    3399   BIC:                            -1888.
Df Model:                           1                                         
Covariance Type:            nonrobust                                         
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const          3.1386      0.006    500.416      0.000       3.126       3.151
x1            -0.0002   3.19e-06    -63.205      0.000      -0.000      -0.000
==============================================================================
Omnibus:                      538.805   Durbin-Watson:                   0.014
Prob(Omnibus):                  0.000   Jarque-Bera (JB):              149.447
Skew:                          -0.227   Prob(JB):                     3.53e-33
Kurtosis:                       2.079   Cond. No.                     3.93e+03
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 3.93e+03. This might indicate that there are
strong multicollinearity or other numerical problems.

"RESULTADOS DE LOS MODELOS PARA AMBAS SERIES"

In [21]:
original_data = ARGOS["Apertura"]
In [17]:
import plotly.subplots as sp
import plotly.graph_objects as go

# Crear subgráficos con make_subplots
fig = sp.make_subplots(rows=1, cols=2, subplot_titles=('Serie original con ajuste de tendencia', 'Serie en escala logarítmica con ajuste de tendencia'))

# Agregar trazas al primer panel
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=original_data, mode='lines', name='Serie original', line=dict(color='blue')), row=1, col=1)
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=fit_Apertura_original.fittedvalues, mode='lines', name='Ajuste de tendencia', line=dict(color='red')), row=1, col=1)

# Agregar trazas al segundo panel
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=log_original_data, mode='lines', name='Serie en escala logarítmica', line=dict(color='blue')), row=1, col=2)
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=fit_logApertura_log.fittedvalues, mode='lines', name='Ajuste de tendencia', line=dict(color='red')), row=1, col=2)

# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', row=1, col=1)
fig.update_xaxes(title_text='Fecha', row=1, col=2)

# Actualizar el diseño del eje y para el primer panel
fig.update_yaxes(title_text='Valor en escala original', row=1, col=1)

# Actualizar el diseño del eje y para el segundo panel
fig.update_yaxes(title_text='Valor en escala log', row=1, col=2)

# Mostrar el gráfico
fig.show()
In [22]:
# Eliminamos la tendencia de la serie original
Apertura_sin_tendencia = original_data - fit_Apertura_original.fittedvalues

# Eliminamos la tendencia de la serie en escala logarítmica
logApertura_sin_tendencia = log_original_data - fit_logApertura_log.fittedvalues
In [23]:
import plotly.subplots as sp
import plotly.graph_objects as go
import pandas as pd
import statsmodels.api as sm

# Calcular autocorrelaciones para la serie en escala original
autocorrelation_original = sm.tsa.acf(Apertura_sin_tendencia, nlags=len(Apertura_sin_tendencia)-1)

# Crear una figura de Plotly para la serie en escala original
fig_original = go.Figure()

# Agregar la serie en escala original
fig_original.add_trace(go.Scatter(x=ARGOS['Fecha'], y=Apertura_sin_tendencia, mode='lines', name='Serie en escala original', line=dict(color='blue')))

# Actualizar el diseño del eje x y y
fig_original.update_xaxes(title_text='Fecha')
fig_original.update_yaxes(title_text='Valor en escala original')

# Mostrar la serie en escala original
fig_original.show()

# Crear una figura de Plotly para el autocorrelograma en escala original
fig_autocorrelation_original = go.Figure()

# Agregar el autocorrelograma en escala original
fig_autocorrelation_original.add_trace(go.Bar(x=list(range(len(Apertura_sin_tendencia))), y=autocorrelation_original, name='Autocorrelograma en escala original', marker=dict(color='blue')))

# Actualizar el diseño del eje x y y
fig_autocorrelation_original.update_xaxes(title_text='Lags')
fig_autocorrelation_original.update_yaxes(title_text='Autocorrelación')

# Agregar Range Slider para seleccionar un rango de lags
fig_autocorrelation_original.update_layout(
    xaxis=dict(title='Lags', rangeslider=dict(visible=True), type='linear')
)

# Mostrar el autocorrelograma en escala original
fig_autocorrelation_original.show()
In [24]:
import plotly.graph_objects as go
import statsmodels.api as sm

# Calcular autocorrelaciones para la serie en escala logarítmica
autocorrelation_log = sm.tsa.acf(logApertura_sin_tendencia, nlags=len(logApertura_sin_tendencia)-1)

# Crear una figura de Plotly para la serie en escala logarítmica
fig_log = go.Figure()

# Agregar la serie en escala logarítmica
fig_log.add_trace(go.Scatter(x=ARGOS['Fecha'], y=logApertura_sin_tendencia, mode='lines', name='Serie en escala logarítmica', line=dict(color='blue')))

# Actualizar el diseño del eje x y y
fig_log.update_xaxes(title_text='Fecha')
fig_log.update_yaxes(title_text='Valor en escala logarítmica')

# Mostrar la serie en escala logarítmica
fig_log.show()

# Crear una figura de Plotly para el autocorrelograma en escala logarítmica
fig_autocorrelation_log = go.Figure()

# Agregar el autocorrelograma en escala logarítmica
fig_autocorrelation_log.add_trace(go.Bar(x=list(range(len(logApertura_sin_tendencia))), y=autocorrelation_log, name='Autocorrelograma en escala logarítmica', marker=dict(color='blue')))

# Actualizar el diseño del eje x y y
fig_autocorrelation_log.update_xaxes(title_text='Lags')
fig_autocorrelation_log.update_yaxes(title_text='Autocorrelación')

# Agregar Range Slider para seleccionar un rango de lags
fig_autocorrelation_log.update_layout(
    xaxis=dict(title='Lags', rangeslider=dict(visible=True), type='linear')
)

# Mostrar el autocorrelograma en escala logarítmica
fig_autocorrelation_log.show()

DESCOMPOSICION DE LAS SERIES

ESCALA ORIGINAL

In [21]:
import pandas as pd
import plotly.graph_objects as go
from statsmodels.tsa.seasonal import seasonal_decompose

# Descomposición estacional utilizando seasonal_decompose
result = seasonal_decompose(ARGOS['Apertura'], model='additive', period=13)  # Ajusta el período según sea necesario

# Crear una figura de Plotly para la descomposición estacional
fig = go.Figure()

# Agregar la serie original a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=ARGOS['Apertura'], mode='lines', name='Serie Original', visible=True))

# Configurar títulos y etiquetas de ejes
titles = ['Serie Original', 'Tendencia', 'Estacionalidad', 'Residual']
y_labels = ['Valor', 'Tendencia', 'Estacionalidad', 'Residual']

# Crear botones para cambiar entre los gráficos
buttons = []
for i, title in enumerate(titles):
    visibility = [False] * len(titles)
    visibility[i] = True
    button = dict(label=title,
                  method="update",
                  args=[{"visible": visibility},
                        {"title": title,
                         "yaxis": {"title": {"text": y_labels[i]}}}],
                  )
    buttons.append(button)

# Agregar la tendencia a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.trend, mode='lines', name='Tendencia', visible=False))

# Agregar la estacionalidad a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.seasonal, mode='lines', name='Estacionalidad', visible=False))

# Agregar el residuo a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.resid, mode='lines', name='Residual', visible=False))

# Agregar botones al layout
fig.update_layout(
    updatemenus=[
        {
            "buttons": buttons,
            "direction": "down",
            "showactive": True,
            "x": 0.5,
            "xanchor": "center",
            "y": 1.15,
            "yanchor": "top"
        }
    ]
)

# Mostrar la figura
fig.show()

ESCALA LOG

In [28]:
import pandas as pd
import plotly.graph_objects as go
from statsmodels.tsa.seasonal import seasonal_decompose

# Descomposición estacional utilizando seasonal_decompose
result = seasonal_decompose(np.log(ARGOS['Apertura']), model='additive', period=13)  # Ajusta el período según sea necesario

# Crear una figura de Plotly para la descomposición estacional
fig = go.Figure()

# Agregar la serie original en escala logarítmica a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=np.log(ARGOS['Apertura']), mode='lines', name='Serie Original', visible=True))

# Configurar títulos y etiquetas de ejes
titles = ['Serie Original', 'Tendencia', 'Estacionalidad', 'Residual']
y_labels = ['Valor', 'Tendencia', 'Estacionalidad', 'Residual']

# Crear botones para cambiar entre los gráficos
buttons = []
for i, title in enumerate(titles):
    visibility = [False] * len(titles)
    visibility[i] = True
    button = dict(label=title,
                  method="update",
                  args=[{"visible": visibility},
                        {"title": title,
                         "yaxis": {"title": {"text": y_labels[i]}}}],
                  )
    buttons.append(button)

# Agregar la tendencia a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.trend, mode='lines', name='Tendencia', visible=False))

# Agregar la estacionalidad a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.seasonal, mode='lines', name='Estacionalidad', visible=False))

# Agregar el residuo a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.resid, mode='lines', name='Residual', visible=False))

# Agregar botones al layout
fig.update_layout(
    updatemenus=[
        {
            "buttons": buttons,
            "direction": "down",
            "showactive": True,
            "x": 0.5,
            "xanchor": "center",
            "y": 1.15,
            "yanchor": "top"
        }
    ]
)

# Mostrar la figura
fig.show()

DIFERENCIA ORDINARA

In [48]:
import pandas as pd
import numpy as np
import plotly.graph_objects as go

# Diferencia ordinaria de la serie original
diff_serie = ARGOS['Apertura'].diff(periods=1)

# Diferencia ordinaria de la serie en escala logarítmica
diff_lserie = np.diff(np.log(ARGOS['Apertura']))

# Crear una figura de Plotly para las diferencias ordinarias
fig = go.Figure()

# Agregar la diferencia ordinaria de la serie original a la figura
fig.add_trace(go.Scatter(x=ARGOS.index[1:], y=diff_serie, mode='lines', name='Diferencia Ordinaria Serie Original', visible=True))

# Agregar la diferencia ordinaria de la serie en escala logarítmica a la figura
fig.add_trace(go.Scatter(x=ARGOS.index[1:], y=diff_lserie, mode='lines', name='Diferencia Ordinaria Serie en Escala Logarítmica', visible=False))

# Configurar título y etiquetas de ejes
fig.update_layout(title='Diferencia Ordinaria de la Serie Original y en Escala Logarítmica',
                  xaxis_title='Tiempo',
                  yaxis_title='Diferencia')

# Configurar botón para cambiar entre las diferencias ordinarias
fig.update_layout(
    updatemenus=[
        {
            "buttons": [
                {
                    "args": [{"visible": [True, False]}, {"title": "Diferencia Ordinaria Serie Original"}],
                    "label": "Serie Original",
                    "method": "update"
                },
                {
                    "args": [{"visible": [False, True]}, {"title": "Diferencia Ordinaria Serie en Escala Logarítmica"}],
                    "label": "Serie en Escala Log",
                    "method": "update"
                }
            ],
            "direction": "down",
            "showactive": True,
            "x": 0.5,
            "xanchor": "center",
            "y": 1.15,
            "yanchor": "top"
        }
    ]
)

# Mostrar la figura
fig.show()

RELACIONES NO LINEALES USANDO LA DISPERSION

ESCALA ORIGINAL

In [66]:
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Crear una figura con subtramas para mostrar todas las gráficas en una cuadrícula
fig = make_subplots(rows=4, cols=3, subplot_titles=[f'Relaciones t y t+{i}' for i in range(1, 13)], 
                    horizontal_spacing=0.1, vertical_spacing=0.1)

# Añadir cada relación no lineal de dispersión a la figura
for i in range(1, 13):
    row = (i - 1) // 3 + 1
    col = (i - 1) % 3 + 1
    scatter = go.Scatter(x=diff_serie[:-i], y=diff_serie.shift(-i)[:-i], mode='markers', name=f'Relaciones t y t+{i}')
    fig.add_trace(scatter, row=row, col=col)

# Configurar título y etiquetas de ejes
fig.update_layout(title='Relaciones No Lineales de Dispersión',
                  xaxis_title='Apertura(t)',
                  yaxis_title='Apertura(t + i)',
                  height=720, width=1080)  # Ajustar el tamaño de la figura

# Mostrar la figura
fig.show()

ESCALA LOG

In [67]:
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# Convertir la serie en escala logarítmica a un objeto de Pandas Series
diff_lserie = pd.Series(diff_lserie)

# Crear una figura con subtramas para mostrar todas las gráficas en una cuadrícula
fig = make_subplots(rows=4, cols=3, subplot_titles=[f'Relaciones t y t+{i}' for i in range(1, 13)], 
                    horizontal_spacing=0.1, vertical_spacing=0.1)

# Añadir cada relación no lineal de dispersión a la figura
for i in range(1, 13):
    row = (i - 1) // 3 + 1
    col = (i - 1) % 3 + 1
    scatter = go.Scatter(x=diff_lserie[:-i], y=diff_lserie.shift(-i)[:-i], mode='markers', name=f'Relaciones t y t+{i}')
    fig.add_trace(scatter, row=row, col=col)

# Configurar título y etiquetas de ejes
fig.update_layout(title='Relaciones No Lineales de Dispersión - Serie en Escala Logarítmica',
                  xaxis_title='Apertura(t)',
                  yaxis_title='Apertura(t + i)',
                  height=720, width=1080)  # Ajustar el tamaño de la figura

# Mostrar la figura
fig.show()

ANALISIS DE AUTOCORRELACION Y AUTOCORRELACION PARCIAL

ESCALA ORIGINAL

In [79]:
import plotly.graph_objects as go
from statsmodels.tsa.stattools import acf, pacf
import numpy as np

# Calcular ACF y PACF
acf_values, acf_confint = acf(diff_serie, nlags=100, fft=True, alpha=0.1)

# Gráfico de ACF
fig_acf = go.Figure()
fig_acf.add_trace(go.Bar(x=list(range(1, 100)), y=acf_values[1:], error_y=dict(type='data', array=acf_confint[1:, 1]-acf_values[1:])))
fig_acf.update_layout(title="Serie diferenciada de costos - ACF", xaxis_title="Lag", yaxis_title="Autocorrelación")
fig_acf.show()
In [78]:
pacf_values, pacf_confint = pacf(diff_serie, nlags=100, alpha=0.1)

# Gráfico de PACF
fig_pacf = go.Figure()
fig_pacf.add_trace(go.Bar(x=list(range(1, 100)), y=pacf_values[1:], error_y=dict(type='data', array=pacf_confint[1:, 1]-pacf_values[1:])))
fig_pacf.update_layout(title="Serie diferenciada de costos - PACF", xaxis_title="Lag", yaxis_title="Autocorrelación parcial")
fig_pacf.show()

No se observan los graficos de Autocorrelacion y Autocorrelacion parcial para la serie diferenciadad con los datos en la escala original, esto significa algo?

ESCALA LOG

In [84]:
import plotly.graph_objects as go
from statsmodels.tsa.stattools import acf, pacf

# Calcular ACF y PACF
acf_values_log, acf_confint_log = acf(diff_lserie, nlags=100, fft=True, alpha=0.05)
pacf_values_log, pacf_confint_log = pacf(diff_lserie, nlags=100, alpha=0.05)

# Gráfico de ACF
fig_acf_log = go.Figure()
fig_acf_log.add_trace(go.Bar(x=list(range(1, 100)), y=acf_values_log[1:], error_y=dict(type='data', array=acf_confint_log[1:, 1]-acf_values_log[1:])))
fig_acf_log.update_layout(title="Serie diferenciada y con logaritmo de costos - ACF", xaxis_title="Lag", yaxis_title="Autocorrelación")
fig_acf_log.show()
In [85]:
# Gráfico de PACF
fig_pacf_log = go.Figure()
fig_pacf_log.add_trace(go.Bar(x=list(range(1, 100)), y=pacf_values_log[1:], error_y=dict(type='data', array=pacf_confint_log[1:, 1]-pacf_values_log[1:])))
fig_pacf_log.update_layout(title="Serie diferenciada y con logaritmo de costos - PACF", xaxis_title="Lag", yaxis_title="Autocorrelación parcial")
fig_pacf_log.show()

INDICE DE INFORMACION MUTUA

Indice de informacion mutua tambien contrasta varias de los rezagos, vas por buen camino

ESCALA ORIGINAL

In [ ]:
#pip install pyinform
In [95]:
import numpy as np
import plotly.graph_objects as go

# Función para plotear el gráfico de Lag Plot para un lag específico
def lag_plot(x, lag=1):
    x_lagged = x[:-lag]
    x_shifted = x[lag:]
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5)))
    corr_value = np.corrcoef(x_lagged, x_shifted)[0, 1]
    fig.add_annotation(text=f'Correlation: {corr_value:.2f}', x=x.max() * 0.9, y=x.min() * 0.9, showarrow=False)
    fig.update_layout(title=f"Lag Plot - Lag {lag}", xaxis_title="Lag(t)", yaxis_title=f"Lag(t + {lag})")
    fig.show()

# Agregar botones para cada gráfico de Lag Plot
buttons = []
for lag in range(1, 13):
    button = dict(label=f"Lag {lag}",
                  method="update",
                  args=[{"visible": [False] * (lag - 1) + [True] + [False] * (12 - lag)},
                        {"title": f"Lag Plot - Lag {lag}"}])
    buttons.append(button)

# Configurar la figura con los gráficos de Lag Plot
fig = go.Figure()
for lag in range(1, 13):
    x = ARGOS['Apertura']
    x_lagged = x[:-lag]
    x_shifted = x[lag:]
    fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5), visible=False))

# Agregar el primer botón activado por defecto
fig.update_layout(updatemenus=[{"active": 0, "buttons": buttons}])

# Configurar diseño y mostrar figura
fig.update_layout(title="Lag Plots - Lag 1", xaxis_title="Lag(t)", yaxis_title="Lag(t + lag)")
fig.show()
In [102]:
import numpy as np
import plotly.graph_objects as go
import pyinform

# Calcular el índice de información mutua para los primeros 12 lags de Apertura
max_lag = 50
lags = list(range(1, max_lag+1))
ami_apertura = [pyinform.mutualinfo.mutual_info(np.array(ARGOS['Apertura'][i:]), np.array(ARGOS['Apertura'][:-i])) for i in lags]

# Gráfico del Índice de Información Mutua para los primeros 12 lags de Apertura
fig_ami = go.Figure()
fig_ami.add_trace(go.Scatter(x=lags, y=ami_apertura, mode='lines', name='Mutual Information'))
fig_ami.update_layout(title="Índice de Información Mutua (Lags 1-12) - Apertura", xaxis_title="Lag", yaxis_title="Mutual Information (Bits)")
fig_ami.show()

ESCALA LOG

In [99]:
import plotly.graph_objects as go
import numpy as np
import pyinform

# Función para plotear el gráfico de Lag Plot para un lag específico
def lag_plot(x, lag=1):
    x_lagged = x[:-lag]
    x_shifted = x[lag:]
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5)))
    corr_value = np.corrcoef(x_lagged, x_shifted)[0, 1]
    fig.add_annotation(text=f'Correlation: {corr_value:.2f}', x=x.max() * 0.9, y=x.min() * 0.9, showarrow=False)
    fig.update_layout(title=f"Lag Plot - Lag {lag}", xaxis_title="Lag(t)", yaxis_title=f"Lag(t + {lag})")
    fig.show()

# Crear una lista de botones para seleccionar cada gráfico de Lag Plot individualmente
buttons = []
for lag in range(1, 13):
    button = dict(label=f"Lag {lag}",
                  method="update",
                  args=[{"visible": [False] * (lag - 1) + [True] + [False] * (12 - lag)},
                        {"title": f"Lag Plot - Lag {lag}"}])
    buttons.append(button)

# Configurar la figura con los gráficos de Lag Plot
fig = go.Figure()
for lag in range(1, 13):
    x = np.log(ARGOS['Apertura'])
    x_lagged = x[:-lag]
    x_shifted = x[lag:]
    fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5), visible=False))

# Agregar el primer botón activado por defecto
fig.update_layout(updatemenus=[{"active": 0, "buttons": buttons}])

# Configurar diseño y mostrar figura
fig.update_layout(title="Lag Plots - Lag 1", xaxis_title="Lag(t)", yaxis_title="Lag(t + lag)")
fig.show()
In [101]:
# Calcular el índice de información mutua para la serie en escala logarítmica
lag_max = 50
ami_logapertura = [pyinform.mutualinfo.mutual_info(np.array(np.log(ARGOS['Apertura'][i:])), np.array(np.log(ARGOS['Apertura'][:-i]))) for i in range(1, lag_max+1)]

# Graficar el índice de información mutua
fig_ami = go.Figure()
fig_ami.add_trace(go.Scatter(x=list(range(1, lag_max+1)), y=ami_logapertura, mode='lines'))
fig_ami.update_layout(title="Índice de Información Mutua - logApertura", xaxis_title="Lag", yaxis_title="Mutual Information (Bits)")
fig_ami.show()

ESTACIONALIDAD DE LAS SUBSERIES

Monthplot lo que hace es tomar cada enero y compararlo con la informacion que se tiene de cada año para ese mes y aspi suceviamente, se muestra un grafico el cual corresponde 12 subgraficacos cada uno respresentando un mes y donde el eje x es el año (vas por buen camino solo faltan los otros meses)

In [47]:
import pandas as pd
import matplotlib.pyplot as plt

# Función para graficar subseries mensuales
def monthplot(series):
    # Convertir el índice a un índice de fecha si aún no lo es
    if not isinstance(series.index, pd.DatetimeIndex):
        series.index = pd.to_datetime(series.index)
    
    # Dividir la serie en subseries mensuales
    subseries = [series[series.index.month == i] for i in range(1, 13)]
    
    # Configurar la figura
    fig, axes = plt.subplots(4, 3, figsize=(15, 10), sharex=True, sharey=True)
    fig.suptitle('Explorando la estacionalidad subseries')

    # Graficar cada subserie mensual
    for i, ax in enumerate(axes.flatten()):
        ax.plot(subseries[i])
        ax.set_title(f'Mes {i+1}')

    plt.tight_layout()
    plt.show()

# Utilizar la función monthplot con tu serie de tiempo
monthplot(diff_serie)
No description has been provided for this image
In [ ]:
 
In [ ]:
 
In [ ]: